package systems.configurations;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.InvalidPropertiesFormatException;
import java.util.Properties;
/**
 * The SystemConfiguration is the class used to check all the system parameters.
 * This class is based on the singleton design pattern.
 * @author Baptiste Legrand & Benjamin Orman
 * @version 2.0
 */
public class SystemConfiguration {
  // The path to the configuration file
  private static String configFilePath = "config/SystemConfig.xml";
  // The File Descriptor (Input Stream) used to load the config file
  private static InputStream is_configFile ;
  // The properties contening all the properties load from the config file.
  private static Properties SystemConfigurationProperties = new Properties();
  // The instance of this class since this Class is based on the Singleton DP.
  private static SystemConfiguration instanceSystemConfiguration  = new SystemConfiguration();

  /**
   * This constructor create a SystemConfiguration and load the properties store in the SystemConfig.xml file.
   */
  private SystemConfiguration()
  {
    reload();
  }
  /**
   * This method return the SystemConfiguration instance.
   * @return instanceSystemConfiguration : the SystemConfiguration instance.
   */
  public static SystemConfiguration getInstance(){
    return instanceSystemConfiguration;
  }

  /**
   * This method return the SystemConfiguration properties.
   * @return SystemConfigurationProperties : the SystemConfiguration properties.
   */	
  public static Properties getProperties(){
    return SystemConfigurationProperties;
  }

  /**
   * This method check if all the parameters stock in config files are ok( i.e dir and file exists).
   * If the check fails then it returns false and display the errors message.
   * @return True if all the parameters in the config files are check. Else False;
   */
  public boolean checkSystemConfigProperties(){
    String tmp_file_path;
    String tmp_key, tmp_value, errorMsg;
    boolean configOk = true;
    Enumeration<Object> enumProperties = SystemConfigurationProperties.keys(); // Getting all the key of the properties.

    errorMsg = "";

    while(enumProperties.hasMoreElements())
    {
      tmp_key = (String)enumProperties.nextElement();
      tmp_value = SystemConfigurationProperties.getProperty(tmp_key);
      if (tmp_key.endsWith(".dir") )
      {
        if(!directoryExists(tmp_value))
        {
          configOk = false;
          errorMsg += "\t-"+tmp_value+" doesn't look to be a directory or doesn't exist.\n";
        }
      }
      else if( tmp_key.endsWith(".file"))
      {
        tmp_file_path = SystemConfigurationProperties.getProperty(tmp_key.substring(0, tmp_key.length()-".file".length()).concat(".dir") );

        if(tmp_file_path == "null") //Si on ne trouve pas une properties .dir associ� au .file alors on leve une erreur.
        {
          configOk = false;
          errorMsg += "\t-"+tmp_key+" doesn't look to be be attach to a directory in the properties file. The directory must be identified by the following key :"+tmp_value.substring(0, tmp_value.length()-".file".length()).concat(".dir")+".\n";
        }
        //Sinon (un repertoire est attach� au fichier dans le fichier properties on verifie que le repertoire et le fichier existe. 
        else
        {
          if(!directoryExists(tmp_file_path)) //Si le repertoire n'existe pas alors on enregistre l'erreur;
          {
            configOk = false;
            errorMsg += "\t-"+tmp_file_path+" doesn't look to be a directory or doesn't exist.\n";
          }
          else // Si le repertoire existe alors on verifier que le fichier existe
          {
            if(!fileExists(tmp_file_path, tmp_value))
            {
              configOk = false;
              errorMsg += "\t-"+tmp_file_path+tmp_value+" doesn't look to be a file or doesn't exist.\n";
            }
          }
        }
      }
    }
    if(!configOk)
    {
      errorMsg = "Error during SystemConfiguration files checking: \n" + errorMsg;
      System.out.println(errorMsg);
    }
    return configOk;
  }

  /**
   * This function check if the path of the directory passed in parameter exists.
   * @param path is the path of the directory that we want to check.
   * @return true if the directory exists, else false.
   */
  public static boolean directoryExists(String path)
  {
    File tmp_File ;

    if(!path.endsWith("/"))
      path = path.concat("/");

    tmp_File = new File(path);
    if(! tmp_File.isDirectory() || !tmp_File.exists())
      return false;
    return true;		
  }
  /**
   * This function check if the full path (path+fileName) in parameter exists.
   * @param path is the path of the directory where the file is.
   * @param fileName is the name of the file itself.
   * @return true if the directory exists, else false.
   */
  public static boolean fileExists(String path, String fileName)
  {
    File tmp_File ;
    if(!path.endsWith("/"))
      path = path.concat("/");
    tmp_File = new File(path+fileName);

    if(! tmp_File.isFile() || !tmp_File.exists()) 
      return false;
    return true;
  }

  /**
   * Load the properties contain in the XML file.
   */
  public static void reload() {
    try {
      SystemConfiguration.is_configFile = new FileInputStream(configFilePath);

    } catch (FileNotFoundException e1) {
      System.out.println(
          "Exception with the following file : "+configFilePath+
      ". File not found. Check the path");
    }
    try { // On charge les Properties depuis le fichier
      SystemConfigurationProperties.loadFromXML(SystemConfiguration.is_configFile);
    } catch (InvalidPropertiesFormatException e) {
      System.out.println(
          "Invalid Properties Format. Please check the following file : "
          +configFilePath);
    } catch (IOException e) {
      System.out.println(
          "Input/Output Exception with the following file : "
          +configFilePath);
      e.printStackTrace();
    } catch (Exception e){
      System.out.println(
          "Exception with the following file : "
          +configFilePath);
          e.printStackTrace();
    }
  }
  
  /**
   * Return the Path of the config file
   * @return String - The path of the config file.
   */
  public static String getConfigFilePath()
  {
    return SystemConfiguration.configFilePath;
  }
}
